/*****************************************************************
Mix3D WebGL Game Engine
Copyright (c) fantasy ( fantasy.x2x@gmail.com )
Listens:
Distributed under the Boost Software License, Version 1.0.
http://www.boost.org/LICENSE_1_0.txt
 ****************************************************************/
/**
 * @Desc    : image
 * @Author  : fantasy(fantasy.x2x@gmail.com)
 */
//////////////////////////////////////////////////////////////////
if(typeof(Mix3D) === 'undefined')
{
  Mix3D = {};
};
(function(Mix3D){
//////////////////////////////////////////////////////////////////
// image pix data type define
Mix3D.PDT_S8 = 9;
Mix3D.PDT_U8 = 10;
Mix3D.PDT_S16 = 11;
Mix3D.PDT_U16 = 12;
Mix3D.PDT_S32 = 13;
Mix3D.PDT_U32 = 14;
Mix3D.PDT_F32 = 15;
// image format
Mix3D.IMG_Alpha = 16;
Mix3D.IMG_RGB = 17;
Mix3D.IMG_RGBA =18;
Mix3D.IMG_LU = 19;
Mix3D.IMG_LA = 20;
//////////////////////////////////////////////////////////////////
//
//        Image
//
//////////////////////////////////////////////////////////////////
Mix3D.Image = function()
{
  Mix3D.Resource.call(this);
  this.imageIns = undefined;
  this.pixDataType = Mix3D.PIX_U8;
  this.imgFormat = Mix3D.IMG_RGBA;
  this.urls = undefined;
};

Mix3D.Image.prototype.constructor = Mix3D.Image;
Mix3D.Image.prototype.className = 'Image';

Mix3D.Image.prototype.getChannelCount = function()
{
  if( this.imgFormat === Mix3D.IMG_RGB)return 3;
  else if( this.imgFormat === Mix3D.IMG_RGBA)return 4;
  else if( this.imgFormat === Mix3D.IMG_LA)return 2;
  return 1;
};

Mix3D.Image.prototype.getPixDataSize = function()
{
  if( this.pixDataType === Mix3D.PDT_S16 || this.pixDataType === Mix3D.PDT_U16)
  {  return 2; }
  else if( this.pixDataType === Mix3D.PDT_S32 || 
           this.pixDataType === Mix3D.PDT_U32 ||
           this.pixDataType === Mix3D.PDT_F32)
  {
    return 4;
  }
  return 1;
};

Mix3D.Image.prototype.getData = function()
{
  if(this.imageIns)
  {
    if(this.imageIns.data)return this.imageIns.data;
   
    return this.imageIns.getContext( '2d' ).getImageData( 0, 0, this.imageIns.width, this.imageIns.height );
  }
  return null;
};

Mix3D.Image.prototype.setPixDataType = function(pixDataType)
{
  this.pixDataType = pixDataType; return this;
};
Mix3D.Image.prototype.PixS8 = function(){ this.pixDataType = Mix3D.PDT_S8; return this;};
Mix3D.Image.prototype.PixU8 = function() { this.pixDataType = Mix3D.PDT_U8; return this; };
Mix3D.Image.prototype.PixS16 = function() { this.pixDataType = Mix3D.PDT_S16; return this; };
Mix3D.Image.prototype.PixU16 = function() { this.pixDataType = Mix3D.PDT_U16; return this; };
Mix3D.Image.prototype.PixS32 = function() { this.pixDataType = Mix3D.PDT_S32; return this; };
Mix3D.Image.prototype.PixU32 = function() { this.pixDataType = Mix3D.PDT_U32; return this; };
Mix3D.Image.prototype.PixF32 = function() { this.pixDataType = Mix3D.PDT_F32; return this; };
Mix3D.Image.prototype.UseAlpha = function() { this.imgFormat = Mix3D.IMG_Alpha; return this; };
Mix3D.Image.prototype.UseRGB = function() { this.imgFormat = Mix3D.IMG_RGB; return this; };
Mix3D.Image.prototype.UseRGBA = function() { this.imgFormat = Mix3D.IMG_RGBA; return this; };
Mix3D.Image.prototype.UseLU = function() { this.imgFormat = Mix3D.IMG_LU; return this; };
Mix3D.Image.prototype.UseLA = function() { this.imgFormat = Mix3D.IMG_LA; return this; };
Mix3D.Image.prototype.setUrls = function( urls ) { this.urls = urls; return true; };

Mix3D.Image.prototype.getWidth = function(){ return this.imageIns.width; };
Mix3D.Image.prototype.getHeight = function() { return this.imageIns.Height; };
Mix3D.Image.prototype.buildData = function(width, height)
{
  var size,image,data;
	width = (width!==undefined && width>0) ? width : 1;
	height = (height !== undefined && height>0) ? height : 1; 
	
	size = width*height*this.getChannelCount();

	image = new Image();
	image.width = width;
	image.height= height;
	if(this.pixDataType ===Mix3D.PDT_S8)
	  data = new Sint8Array( size );
	else if( this.pixDataType === Mix3D.PDT_U8)
	  data = new Uint8Array( size );
	else if( this.pixDataType === Mix3D.PDT_S16)
	  data = new Sint16Array( size );
	else if( this.pixDataType === Mix3D.PDT_U16)
	  data = new Uint16Array( size );
	else if( this.pixDataType === Mix3D.PDT_S32)
	  data = new Sint32Array( size );
	else if( this.pixDataType === Mix3D.PDT_U32)
	  data = new Uint32Array( size );
	else if( this.pixDataType === Mix3D.PDT_F32)
	  data = new Float32Array( size );
	image.data = data;
	this.imageIns = image;
	this.onReady();
};

Mix3D.Image.prototype.buildCanvas = function(width, height, color, alpha )
{
  this.PixU8().ImgRGBA();
  var canvas, image, imgData, rgba;
  width = (width!==undefined && width>0) ? width : 1;
  height = (height !== undefined && height>0) ? height : 1;
  canvas = document.createElement( 'canvas' );
  canvas.width = width;
  canvas.height = height;
  image = canvas.getContext( '2d' );
  if(color !== undefined)
  {
    imgData = image.getImageData( 0, 0, width, height );
    rgba = [255,255,255,255];
    rgba[0] = Math.floor( color.r * 255 );
    rgba[1] = Math.floor( color.g * 255 );
    rgba[2] = Math.floor( color.b * 255 );
    
    if(alpha!==undefined)rgba[3]=Math.floor(alpha*255);
    
    for( var i=0, l=imgData.data.length; i<l;  i+=4)
    {
      imgData.data[ i ] = rgba[0];    //R
      imgData.data[ i + 1 ] = rgba[1];//G
      imgData.data[ i + 2 ] = rgba[2];//B
      imgData.data[ i + 3 ] = rgba[3];//A
    }
    image.putImageData( imgData, 0, 0 );
  }
  this.canvas = canvas;
  this.imageIns = this.canvas;
  this.onReady();
};

Mix3D.Image.prototype.loadFile = function( urls, callback)
{
  this.urls = urls;
  var scope = this;
  if( urls.constructor === Array )
  {
	  var images = [];
	  images.loadCount = 0;
	  images._fileCount = urls.length;
	  for (var i = 0, l = urls.length; i < l; ++i )
	  {
		  var image = new Image();
		  image.onload = function () 
		  {
			  images.loadCount += 1;
			  if ( images.loadCount === images._fileCount) 
			  {
			    scope.imageIns = images;
			    this.onReady();
			    if(callback)callback(scope);
			  }
		  };
		  image.crossOrigin = 'anonymous';
		  image.src = urls[ i ];
		  images.push(image);
	  }
  }
  else
  {
    var image = new Image();
	  image.onload = function () 
	  {
	    scope.imageIns = image;
	    this.onReady();
	    if(callback)callback(scope);
	  };
	  image.crossOrigin = 'anonymous';
	  image.src = urls;
  }
};

Mix3D.Image.prototype.setChannelValue = function( x, y, value, channel)
{
  var data = this.getData();
  if(data && channel < this.getChannelCount())
  {
	  var pos = x + y*this.imageIns.width*this.getChannelCount() + c;
	  if(this.pixDataType !== Mix3D.PDT_F32)
	  {
	    data[pos]=Math.floor(value);
	  }
	  else
	  {
	    data[pos]=value;
	  }
	}
};

Mix3D.Image.prototype.clear = function(r, g, b, a)
{
  var data = this.getData();
  if(data)
  {
    var size = this.imageIns.width * this.imageIns.height;
    var channelSize = this.getChannelCount();
    for( var i=0, pos=0; i<size; ++i, pos += channelSize)
    {
      switch(channelSize)
      {
        case 1:
         data[pos] = r;
        break;
        case 2:
        data[pos] = r;
        data[pos+1]=g;
        break;
        case 3:
        data[pos]=r;
        data[pos+1]=g;
        data[pos+2]=b;
        break;
        case 4:
        data[pos]= r;
        data[pos+1]=g;
        data[pos+2]=b;
        data[pos+3]=a;
        break;
      }
    }
  }
  return this;
};

Mix3D.Image.prototype.isReady = function()
{ 
  return this.imageIns!==undefined; 
};

Mix3D.Image.prototype.create = function()
{
  if(!this.imageIns && this.urls)
  {
    this.loadFile(this.urls);
  }
  return this.imageIns;
};

Mix3D.Image.prototype.release = function()
{
  if(this.imageIns)
  {
    delete this.imageIns;
    this.imageIns = undefined;
  }
};

Mix3D.Image.prototype.load = function(stream) 
{
  this.name = stream.read('resName');
  this.pixDataType = stream.read('type');
  this.imgFormat = stream.read('format');
  this.urls = stream.read('urls');
};

Mix3D.Image.prototype.save = function(stream)
{
  stream.write('resName', this.name);
  stream.write('type', this.pixDataType);
  stream.write('format', this.imgFormat);
  stream.write('urls', this.urls);
};

Mix3D.protoCopy(Mix3D.Resource, Mix3D.Image);
Mix3D.defineResourceType(Mix3D.Image);
//////////////////////////////////////////////////////////////////
})(Mix3D);// end of function(Mix3D)